/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Xadrez.Modelo;

/**
 *
 * @author Jéssica
 */
public class Match {

    private Board chessboard;
    private Board[] chessboardBackupVetor;
    private int tamanhoVetorDeBackup = 10;
    private int numBackups;
    private boolean[] firstMoveUndoVetor;
    private boolean[] enPassantMoveVetor;
    private Piece[] movedPieceVetor;
    private Piece[] movedPieceTwoVetor;
    private boolean[] firstMoveUndoTwoVetor;
    private Player player1;
    private Player player2;
    private String turn;
    private int numberOfTurns;
    private boolean testeXeque;
    public boolean auxEndGame;
    private boolean endGame;
    private boolean remendoBug;
    private boolean fazendoUndo;
    private Move[] movimentosFeitos;
    private boolean movimentoDesfeito;

    public Match() {
        chessboard = new Board();
        chessboard.resetPositions();
        numberOfTurns = 0;
        numBackups = 0;

        auxEndGame = false;
        endGame = false;
        remendoBug = false;
        fazendoUndo = false;
        movimentoDesfeito = false;

        chessboardBackupVetor = new Board[tamanhoVetorDeBackup];
        firstMoveUndoVetor = new boolean[tamanhoVetorDeBackup];
        movedPieceVetor = new Piece[tamanhoVetorDeBackup];
        movedPieceTwoVetor = new Piece[tamanhoVetorDeBackup];
        firstMoveUndoTwoVetor = new boolean[tamanhoVetorDeBackup];
        enPassantMoveVetor = new boolean[tamanhoVetorDeBackup];



        player1 = new Player("White");
        player2 = new Player("Black");
        turn = "White";

        for (int i = 0; i <= 7; i++) {
            player1.setPiece(chessboard.getGrid()[i][7].getPiece(), i);
        }
        for (int i = 0; i <= 7; i++) {
            player1.setPiece(chessboard.getGrid()[i][6].getPiece(), i + 8);
        }
        for (int i = 0; i <= 7; i++) {
            player2.setPiece(chessboard.getGrid()[i][0].getPiece(), i);
        }
        for (int i = 0; i <= 7; i++) {
            player2.setPiece(chessboard.getGrid()[i][1].getPiece(), i + 8);
        }


    }

    //No método changeTurn, eu botei esse for
    //Pra testar se a promoção funcionaria
    //Ele automaticamente chama promoção pra rainha
    //Deve ser corrigido
    

    private void changeTurn() {
        if (turn.equals("White")) {
            turn = "Black";
        } else {
            turn = "White";
        }
        
       



        // <editor-fold defaultstate="collapsed" desc="promoção">
        for (int i = 0; i <= 7; i++) {

            if (this.getPiece(i, 0) != null) {
                if (this.getPiece(i, 0).toString().equals("peão")) {
                    
                    promoteToQueen(this.getPiece(i, 0));
                }
            }

            if (this.getPiece(i, 7) != null) {
                if (this.getPiece(i, 7).toString().equals("peão")) {
                    
                    promoteToQueen(this.getPiece(i, 0));
                }
            }

        }// </editor-fold>

    }

    public void move(int ox, int oy, int dx, int dy) {

        try {
            Square o = chessboard.getGrid()[ox][oy];
            Square d = chessboard.getGrid()[dx][dy];

            if (o.getPiece() == null) {
            } else {
                if (!o.getPiece().getColor().equals(turn)) {
                    //não pode mexer com a peça do adversário
                } else {


                    for (int i = 0; i <= tamanhoVetorDeBackup - 2; i++) {
                        chessboardBackupVetor[tamanhoVetorDeBackup - 1 - i] = chessboardBackupVetor[tamanhoVetorDeBackup - 2 - i];
                        firstMoveUndoVetor[tamanhoVetorDeBackup - 1 - i] = firstMoveUndoVetor[tamanhoVetorDeBackup - 2 - i];
                        movedPieceVetor[tamanhoVetorDeBackup - 1 - i] = movedPieceVetor[tamanhoVetorDeBackup - 2 - i];
                        movedPieceTwoVetor[tamanhoVetorDeBackup - 1 - i] = movedPieceTwoVetor[tamanhoVetorDeBackup - 2 - i];
                        firstMoveUndoTwoVetor[tamanhoVetorDeBackup - 1 - i] = firstMoveUndoTwoVetor[tamanhoVetorDeBackup - 2 - i];
                        enPassantMoveVetor[tamanhoVetorDeBackup - 1 - i] = enPassantMoveVetor[tamanhoVetorDeBackup - 2 - i];

                    }
                    chessboardBackupVetor[0] = chessboard.backup();

                    if (o.getPiece().isFirstMove()) {
                        this.firstMoveUndoVetor[0] = true;
                    } else {
                        this.firstMoveUndoVetor[0] = false;
                    }

                    if (o.getPiece().getEnPassant()) {
                        this.enPassantMoveVetor[0] = true;
                    } else {
                        this.enPassantMoveVetor[0] = false;
                    }


                    movedPieceVetor[0] = o.getPiece();
                    movedPieceTwoVetor[0] = d.getPiece();

                    if (movedPieceTwoVetor[0] != null) {

                        if (movedPieceTwoVetor[0].isFirstMove()) {
                            this.firstMoveUndoTwoVetor[0] = true;
                        } else {
                            this.firstMoveUndoTwoVetor[0] = false;
                        }

                    } else {
                        this.firstMoveUndoTwoVetor[0] = false;
                    }

                    if (numBackups < tamanhoVetorDeBackup) {
                        numBackups++;
                    }


                    o.getPiece().move(new Move(o, d), chessboard);

                    if (o.getPiece() == null) {



                        //Primeira tentativa de fazer o xeque


                        changeTurn();
                        numberOfTurns++;

                        marcarXeque();

                        if (this.turn.equals("White") && (this.player2.getXeque())) {
                            movimentoDesfeito = true;
                            undoMove(3);

                        } else if (this.turn.equals("Black") && (this.player1.getXeque())) {
                            undoMove(3);
                            movimentoDesfeito = true;
                        } else {
                            movimentoDesfeito = false;
                        }




                    } else { // Desmarcar en passant
                        for (int i = 0; i <= 15; i++) {

                            if (this.player1.getPiece()[i] != null) {
                                if (!(this.player1.getPiece()[i].equals(o.getPiece()))) {
                                    this.player1.getPiece()[i].setEnPassant(false);
                                }
                            }

                            if (this.player2.getPiece()[i] != null) {
                                if (!(this.player2.getPiece()[i].equals(o.getPiece()))) {
                                    this.player2.getPiece()[i].setEnPassant(false);
                                }
                            }

                        }

                    }


                }

            }

        } catch (ArrayIndexOutOfBoundsException e) {
            remendoBug = true;

        }

    }

    private void marcarXeque() {

        Piece reiBranco = player1.getPiece()[4];
        Piece reiPreto = player2.getPiece()[4];
        Square posReiBranco = null;
        Square posReiPreto = null;
        for (int i = 0; i <= 7; i++) {
            for (int j = 0; j <= 7; j++) {
                if (this.getPiece(i, j) != null) {
                    if (chessboard.getGrid()[i][j].getPiece().equals(reiBranco)) {
                        posReiBranco = chessboard.getGrid()[i][j];

                    }
                    if (chessboard.getGrid()[i][j].getPiece().equals(reiPreto)) {
                        posReiPreto = chessboard.getGrid()[i][j];

                    }
                }
            }
        }

        testeXeque = false;

        player1.setXeque(false);
        for (int i = 0; i <= 7; i++) {
            for (int j = 0; j <= 7; j++) {

                if (this.getPiece(i, j) != null) {
                    if (!this.getPiece(i, j).getColor().equals(player1.getColor())) {
                        Move m = new Move(chessboard.getGrid()[i][j], posReiBranco);
                        testeXeque = this.getPiece(i, j).isValidMove(m, chessboard);
                        player1.setXeque(testeXeque);

                    }
                }
                if (testeXeque) {
                    break;
                }
            }
            if (testeXeque) {

                break;
            }
        }


        testeXeque = false;
        player2.setXeque(false);
        for (int i = 0; i <= 7; i++) {
            for (int j = 0; j <= 7; j++) {

                if (this.getPiece(i, j) != null) {
                    if (!this.getPiece(i, j).getColor().equals(player2.getColor())) {

                        Move m = new Move(chessboard.getGrid()[i][j], posReiPreto);
                        testeXeque = this.getPiece(i, j).isValidMove(m, chessboard);
                        player2.setXeque(testeXeque);

                    }
                }
                if (testeXeque) {
                    break;
                }
            }
            if (testeXeque) {

                break;
            }
        }

        if (!player2.getXeque()) {
            System.out.println("Não pegou xeque");
        } else {
            System.out.println("pegou xeque");
        }


    }

    public boolean xequeMate(Player p) {

        if (p.getXeque()) {

            this.endGame = true;

            for (int a = 0; a <= 7; a++) {
                for (int b = 0; b <= 7; b++) {
                    for (int c = 0; c <= 7; c++) {
                        for (int d = 0; d <= 7; d++) {

                            if (this.getPiece(a, b) != null) {
                                if (this.getPiece(a, b).getColor().equals(p.getColor())) {

                                    move(a, b, c, d);

                                    marcarXeque();
                                    if (!p.getXeque()) {
                                        endGame = false;
                                        System.out.println(a + " - " + b + " - " + c + " - " + d);
                                    }
                                    //ou endGame = p.getXeque;

                                    if (this.getPiece(a, b) == null) {
                                        undoMove(3);
                                    }
                                }
                            }

                            if (!endGame) {
                                break;
                            }
                        }
                        if (!endGame) {
                            break;
                        }
                    }
                    if (!endGame) {
                        break;
                    }
                }
                if (!endGame) {
                    break;
                }
            }


        }



        return endGame;
    }

    public boolean getEndGame() {
        return this.endGame;
    }

    public void promoteToQueen(Piece p) {

        for (int x = 0; x <= 15; x++) {
            if (player1.getPiece()[x].equals(p)) {

                player1.setPiece(new Queen("White"), x);

                for (int i = 0; i <= 7; i++) {
                    for (int j = 0; j <= 7; j++) {

                        if (this.getPiece(i, j) != null) {
                            if (this.getPiece(i, j).equals(p)) {
                                chessboard.getGrid()[i][j].setPiece(player1.getPiece()[x]);
                            }

                        }

                    }
                }

            }

            if (player2.getPiece()[x].equals(p)) {

                player2.setPiece(new Queen("Black"), x);

                for (int i = 0; i <= 7; i++) {
                    for (int j = 0; j <= 7; j++) {
                        if (this.getPiece(i, j) != null) {
                            if (this.getPiece(i, j).equals(p)) {
                                chessboard.getGrid()[i][j].setPiece(player2.getPiece()[x]);
                            }

                        }

                    }
                }

            }


        }

    }

    public Piece getPiece(int x, int y) {
        return chessboard.getGrid()[x][y].getPiece();
    }

    public boolean isValidMove(int ox, int oy, int dx, int dy) {

        boolean validate = false;

        Move move = new Move(chessboard.getGrid()[ox][oy], chessboard.getGrid()[dx][dy]);

        if (this.getPiece(ox, oy) != null) {

            try {

                if (chessboard.getGrid()[ox][oy].getPiece().isValidMove(move, chessboard)) {

                    if (this.getPiece(ox, oy).getColor().equals(this.getTurn())) {
                        validate = true;
                    }
                }

            } catch (ArrayIndexOutOfBoundsException e) {
                validate = false;
            }

        }

        return validate;
    }

    public void undoMove(int n) {

        fazendoUndo = true;


        if (numBackups > 0) {

            chessboard = chessboardBackupVetor[0].backup();

            if (this.firstMoveUndoVetor[0]) {
                this.movedPieceVetor[0].setFirstMove(true);
                this.firstMoveUndoVetor[0] = false;
            }

            if (this.enPassantMoveVetor[0]) {
                this.movedPieceVetor[0].setEnPassant(true);
                this.enPassantMoveVetor[0] = false;
            }


            if (this.firstMoveUndoTwoVetor[0]) {
                this.movedPieceTwoVetor[0].setFirstMove(true);
                this.firstMoveUndoTwoVetor[0] = false;
            }

            for (int i = 0; i <= tamanhoVetorDeBackup - 2; i++) {

                chessboardBackupVetor[i] = chessboardBackupVetor[i + 1];

                firstMoveUndoVetor[i] = firstMoveUndoVetor[i + 1];
                movedPieceVetor[i] = movedPieceVetor[i + 1];
                movedPieceTwoVetor[i] = movedPieceTwoVetor[i + 1];
                firstMoveUndoTwoVetor[i] = firstMoveUndoTwoVetor[i + 1];

            }

            changeTurn();
            numberOfTurns--;
            numBackups--;

            testeXeque = false;
            marcarXeque();


        }

        fazendoUndo = false;

    }

    public Square selectSquare(int x, int y) {
        Square s = chessboard.getGrid()[x][y];
        return s;
    }

    public void decrementaTurno() {
        this.numberOfTurns--;
    }

    public Player getPlayer1() {
        return this.player1;
    }

    public Player getPlayer2() {
        return this.player2;
    }

    public void setPlayer1(Player p) {
        this.player1 = p;
    }

    public void setPlayer2(Player p) {
        this.player2 = p;
    }

    public String getTurn() {
        return this.turn;
    }

    public int getNumberOfTurns() {
        return this.numberOfTurns;
    }

    public boolean getRemendoBug() {
        return this.remendoBug;
    }

    public void setRemendoBug(boolean b) {
        this.remendoBug = b;
    }

    public boolean getMovimentoDesfeito() {
        return this.movimentoDesfeito;
    }
}
